package com.dxb.test.forkjoin;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Logger;
import java.util.stream.Collectors;

public class CustomRecursiveTask extends RecursiveTask<String> {
    private static AtomicInteger i = new AtomicInteger(0);
    private String workload = "";
    private static final int THRESHOLD = 4;

    private static Logger logger = Logger.getAnonymousLogger();

    public CustomRecursiveTask(String workload) {
        this.workload = workload;
    }

    @Override
    protected String compute() {
        if (workload.length() > THRESHOLD) {
            return ForkJoinTask.invokeAll(createSubtasks())
                    .stream()
                    .map(ForkJoinTask::join)
                    .collect(Collectors.joining());
        } else {
            return processing(workload);
        }
    }

    private Collection<CustomRecursiveTask> createSubtasks() {
        List<CustomRecursiveTask> subtasks = new ArrayList<>();

        String partOne = workload.substring(0, workload.length() / 2);
        String partTwo = workload.substring(workload.length() / 2);

        subtasks.add(new CustomRecursiveTask(partOne));
        subtasks.add(new CustomRecursiveTask(partTwo));

        return subtasks;
    }

    private String processing(String work) {
        i.incrementAndGet();
        String result = work.toUpperCase();
        logger.info("This result - (" + result + ") - was processed by "
                + Thread.currentThread().getName());
        return result;
    }

    public static void main(String[] args) {
        ForkJoinPool forkJoinPool = ForkJoinPool.commonPool();
        CustomRecursiveTask task = new CustomRecursiveTask("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz");
        //invoke() 方法 fork 任务并等待结果，不需要任何手动连接 ( join )
        String result = forkJoinPool.invoke(task);
        System.out.println(result);
        System.out.println("fork:" + i.get());
        forkJoinPool.shutdown();
    }
}
